package com.quectel.sdk.baidu.img;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.img.ImgUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.quectel.sdk.baidu.AbstractBaiduBCEBaseClient;
import com.quectel.sdk.baidu.model.img.BaiduBCEImgResp;
import com.quectel.util.common.MyFileUtils;
import com.quectel.util.common.Response;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;

/**
 * @author zhangheng
 * @email nolan.zhang@quectel.com
 * @date 2023/5/12 9:28
 * @description new java file header...
 */
@Slf4j
public class BaiduBCEImgClient extends AbstractBaiduBCEBaseClient {

    /**
     * 请求格式支持：PNG、JPG、JPEG、BMP、GIF（仅对首帧进行审核）、Webp、TIFF
     * <p>
     * 图像大小支持：图像要求base64后大于等于5KB，小于等于4MB，最短边大于等于128像素，小于等于4096像素
     */

    public static final HashSet<String> ANTIPORN_SUPPORT_IMAGE_FORMAT =
            new HashSet<String>(Arrays.asList("JPEG", "png", "bmp", "gif"));

    /**
     * 文本检测
     */
    private final static String IMG_CENSOR_URI = "/rest/2.0/solution/v1/img_censor/v2/user_defined";

    /**
     * 校验成功通过的标识
     */
    public static final Integer PASS_CHECK = 1;


    /**
     * 文本检测
     */
    private final static Byte FILE = 1;
    /**
     * 文本检测
     */
    private final static Byte IMG_URL = 2;


    /**
     * 图片base64后的数据 传输图片地址
     *
     * @param imgData
     * @return
     */
    public BaiduBCEImgResp checkByFile(byte[] imgData) {
        String encode = Base64.encode(imgData);

        Map<String, Object> params = new HashMap<>();
        params.put("image", encode);
        return requester.postForm(IMG_CENSOR_URI, params, new TypeReference<BaiduBCEImgResp>() {
        });
    }

    /**
     * 传输图片url
     *
     * @param imgUrl
     * @return
     */

    public BaiduBCEImgResp checkByImgUrl(String imgUrl) {
        Map<String, Object> parmas = new HashMap<>();
        parmas.put("imgUrl", imgUrl);
        return requester.postForm(IMG_CENSOR_URI, parmas, new TypeReference<BaiduBCEImgResp>() {
        });
    }


    public byte[] readFileByBytes(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath);
        }

        ByteArrayOutputStream bos = new ByteArrayOutputStream(((int) file.length()));
        BufferedInputStream in = null;
        try {
            in = new BufferedInputStream(new FileInputStream(file));
            int bufSize = 1024;
            byte[] buffer = new byte[bufSize];
            int len = 0;
            while (-1 != (len = in.read(buffer, 0, bufSize))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            bos.close();
        }
    }

    /**
     * 请求前的检查
     * 请求格式支持：PNG、JPG、JPEG、BMP、GIF（仅对首帧进行审核）、Webp、TIFF
     * <p>
     * 图像大小支持：图像要求base64后大于等于5KB，小于等于4MB，最短边大于等于128像素，小于等于4096像素
     *
     * @param imgInfo
     * @return
     */
    public Response requestPreCheck(ImgInfo imgInfo) {
        //校验图片格式
        String format = getImageFormatByBytes(imgInfo.getImageData());
        if (!ANTIPORN_SUPPORT_IMAGE_FORMAT.contains(format)) {
            return Response.error("不支持的图片格式");
        }
        //校验大小
        if (imgInfo.getFileSizeKB() < 5 || imgInfo.getFileSizeMB() > 4) {
            return Response.error("图片大小不合法");
        }
        int minLength = 0;
        //获取最短边
        if (imgInfo.getWidth() > imgInfo.getHeight()) {
            minLength = imgInfo.getHeight();
        } else {
            minLength = imgInfo.getWidth();
        }
        if (minLength < 128 || minLength > 4096) {
            log.debug("图片要求最短边大于等于128像素，小于等于4096像素");
        }

        return Response.ok();
    }

    @Data
    public static class ImgInfo {
        /**
         * 图片KB大小
         */
        private double fileSizeKB;
        /**
         * 图片MB大小
         */
        private double fileSizeMB;
        /**
         * 图片宽度
         */
        private int width;
        /**
         * 图片高度
         */
        private int height;
        /**
         * 图片url
         */
        private String url;
        /**
         * 图片base64后的地址
         */
        private byte[] imageData;

    }

    /**
     * @param file
     * @return
     */
    public ImgInfo getImgInfoByFile(String file) {
        byte[] imgData = new byte[0];
        try {
            imgData = readFileByBytes(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        double fileSizeKB = imgData.length / 1024.0;
        double fileSizeMB = fileSizeKB / 1024.0;

        BufferedImage read = ImgUtil.read(file);

        ImgInfo imgInfo = new ImgInfo();
        imgInfo.setFileSizeKB(fileSizeKB);
        imgInfo.setFileSizeMB(fileSizeMB);
        imgInfo.setWidth(read.getWidth());
        imgInfo.setHeight(read.getHeight());
        imgInfo.setImageData(imgData);

        return imgInfo;
    }


    /**
     * @param url
     * @return
     */
    public ImgInfo getImgInfoByURL(String url) {
        File file = MyFileUtils.downloadToTempDir(url, true);
        ImgInfo imgInfoByFile = getImgInfoByFile(file.getAbsolutePath());
        imgInfoByFile.setUrl(url);
        return imgInfoByFile;
    }


    public String getImageFormatByBytes(byte[] content) {
        ImageInputStream input = null;
        try {
            input = new MemoryCacheImageInputStream(new ByteArrayInputStream(content));
            return getImageFormat(input);
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public String getImageFormat(ImageInputStream input) {
        Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
        String format = "unknown";
        if (readers.hasNext()) {
            ImageReader reader = readers.next();
            try {
                format = reader.getFormatName();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                reader.dispose();
            }
        }

        return format;
    }

}
